define(["../FSM",
        "dojo/_base/fx",
        "dojo/on",
        "dojo/query",
        "dojo/dom-class",
        "dojo/dom-style",
        "dojo/_base/Deferred",
        "dojo/_base/lang",
        "dojo/domReady!"], function(FSM, fx, on, query, domClass, domStyle, Deferred, lang) {

    var carousel = function (/*container node*/arena, opts) {

        var opts = lang.mixin(
            {
                duration : 400,
                direction: "vertical"
            },
            opts);
        
        var fsm;
        var fwrdButton, bwrdButton, tape, items;

        fwrdButton = query(".button.frwd", arena)[0];
        bwrdButton = query(".button.brwd", arena)[0];
        tape = query(".roll", arena)[0];
        items = query(".item", arena);

        //
        domClass.add(fwrdButton, 'active');
        domClass.add(items[0], 'current');
        
        fsm = new FSM.LinearFSM({
            len: items.length,
            transition_handler: function (from, to) {
                
                var step = to - from;
                var promise = new Deferred();
                
                var _animate_opts = {
                    node: tape,
                    duration: opts.duration,
                    onEnd: function (node) {
                        // items
                        domClass.remove(items[from], 'current');
                        domClass.add(items[to], 'current');

                        // buttons
                        if (to === fsm.max_state) {
                            domClass.remove(fwrdButton, 'active');
                        }
                        if (from === fsm.max_state) {
                            domClass.add(fwrdButton, 'active');
                        }        
                        if (to === fsm.min_state) {
                            domClass.remove(bwrdButton, 'active');
                        }
                        if (from === fsm.min_state) {
                            domClass.add(bwrdButton, 'active');
                        }                       
                        promise.resolve();
                    }
                };

                if (opts.direction === "horizontal") {
                    lang.mixin(_animate_opts, {
                        properties: {
                            left: {end: domStyle.get(tape, 'left') - step*domStyle.get(items[0], 'width')}
                        }
                    });
                } else {
                    lang.mixin(_animate_opts, {
                        properties: {
                            top: {end: domStyle.get(tape, 'top') - step*domStyle.get(items[0], 'height')}
                        }
                    });
                }
                //
                fx.animateProperty(_animate_opts).play();

                return promise;
            }
        });

        //
        on(fwrdButton, "click", function(evt) {
            fsm.fwrd();
        });
        on(bwrdButton, "click", function(evt) {
            fsm.bwrd();
        });
    };

    return carousel;
});
